package com.wang.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.wang.constant.CacheKey;
import com.wang.enums.BizCodeEnum;
import com.wang.enums.SendCodeEnum;
import com.wang.exception.BizException;
import com.wang.interceptor.LoginInterceptor;
import com.wang.mapper.ProductMapper;
import com.wang.model.LoginUser;
import com.wang.request.CartItemRequest;
import com.wang.service.CartService;
import com.wang.service.ProductService;
import com.wang.vo.CartItemVO;
import com.wang.vo.CartVO;
import com.wang.vo.ProductVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import springfox.documentation.spring.web.json.Json;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class CartServiceImpl implements CartService {
    @Autowired
    private RedisTemplate  redisTemplate;

    @Autowired
    private ProductService productService;

    /**
     * 添加商品到购物车
     * @param cartItemRequest
     */
    @Override
    public void addToCart(CartItemRequest cartItemRequest) {
        Integer num = cartItemRequest.getNum();
        Long productId = cartItemRequest.getProductId();

        //获取redis中的购物车
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        Object cartItem = myCartOps.get(productId.toString());
        String result = "";
        if(cartItem != null){
            result = (String) cartItem;
        }

        //如果redis中没有对应的购物车类，这里的put也会成功（并创建一个对应的购物车类）
        if(result.isBlank()){

            //如果购物车中没有对应的商品     添加商品
            CartItemVO  cartItemVO = new CartItemVO();
            ProductVO productVO = productService.findByProductId(productId);
            cartItemVO.setProductId(productId);
            cartItemVO.setNum(num);
            cartItemVO.setTitle(productVO.getTitle());
            cartItemVO.setCoverImg(productVO.getCoverImg());
            cartItemVO.setPrice(productVO.getPrice().intValue());
            myCartOps.put(productId.toString(),JSON.toJSONString(cartItemVO));
        }else{
            //如果购物车中有对应的商品      修改对应商品的数量
            CartItemVO cartItemVO = JSON.parseObject(result, CartItemVO.class);
            cartItemVO.setNum(cartItemVO.getNum() + num);
            myCartOps.put(productId.toString(),JSON.toJSONString(cartItemVO));
        }

    }

    /**
     * 清空购物车
     */
    @Override
    public void clearCart() {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        //不是使用myCartOps.delete(productId),这个是删除键值对，不是删除整个购物车
        redisTemplate.delete(getCartKey());
    }

    /**
     * 查看我的购物车 （数据库中获取购物车中商品最新的价格、图片地址、标题等信息）
     */
    @Override
    public CartVO getMyCart() {
        //获取购物车中所有的商品
        //这里就不设置true，目前不需要这个(有需要再改)   TODO
        List<CartItemVO> cartItemVOList = buildCartItem(false);

        //封装CartVO
        CartVO cartVO = new CartVO();
        cartVO.setCartItemVOList(cartItemVOList);

        return cartVO;
    }

    /**
     * 根据商品Id删除购物车中对应的购物项
     * @param productId
     */
    @Override
    public void deleteCartItem(Long productId) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();

        myCartOps.delete(productId.toString());
    }

    /**
     * 修改购物项商品数
     * TODO  没有进行判断商品数量是否正确的（两种方法，在CartController中写了）
     * @param cartItemRequest
     */
    @Override
    public void upDataCartItemSum(CartItemRequest cartItemRequest) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        Object cacheObj = myCartOps.get(cartItemRequest.getProductId().toString());
        if(cacheObj == null){
            throw new BizException(BizCodeEnum.CART_PRODUCT_NOT_EXIST);
        }
        String obj = (String)cacheObj;
        CartItemVO cartItemVO = JSONObject.parseObject(obj, CartItemVO.class);
        cartItemVO.setNum(cartItemRequest.getNum());
        myCartOps.put(cartItemVO.getProductId().toString(),JSONObject.toJSONString(cartItemVO));
    }

    /**
     * 获取订单中商品详情
     * @param productIdList
     * @return
     */
    @Override
    public List<CartItemVO> confirmOrderCartItems(List<Long> productIdList) {
        List<CartItemVO> cartItemVOList = buildCartItem(true);

        //根据订单中的商品id进行过滤，并清空对应的购物项
        List<CartItemVO> resultList = cartItemVOList.stream().filter(obj -> {
            if (productIdList.contains(obj.getProductId())) {
                this.deleteCartItem(obj.getProductId());
                return true;
            }
            return false;
        }).collect(Collectors.toList());

        return resultList;
    }

    /**
     * 获取购物车中商品   b:是否要获取最新的价格。
     * @param b
     * @return
     */
    private List<CartItemVO> buildCartItem(boolean b) {
        BoundHashOperations<String, Object, Object> myCartOps = getMyCartOps();
        List<Object> values = myCartOps.values();

        List<CartItemVO> cartItemVOList = new ArrayList<>();
        List<Long> productIds = new ArrayList<>();

        for (Object value : values) {
            CartItemVO cartItemVO = JSON.parseObject((String) value, CartItemVO.class);
            cartItemVOList.add(cartItemVO);
            productIds.add(cartItemVO.getProductId());
        }

        //查询商品最新价格
        if(b){
            setProductLastPrice(cartItemVOList,productIds);
        }

        return cartItemVOList;
     }

    /**
     * 设置商品最新价格，标题，图片地址
     * @param cartItemVOList
     * @param productIds
     */
    private void setProductLastPrice(List<CartItemVO> cartItemVOList, List<Long> productIds) {
        List<ProductVO> productVOList = productService.findBYProductIdBatch(productIds);

        //创建一个map,根据商品Id分类  这样可以方便查找cartItemVOList中和productVOList中的相同商品的信息
        Map<Long, ProductVO> productMap = productVOList.stream().collect(Collectors.toMap(ProductVO::getId, Function.identity()));

        for (CartItemVO cartItemVO : cartItemVOList) {
            ProductVO productVO = productMap.get(cartItemVO.getProductId());
            cartItemVO.setPrice(productVO.getPrice().intValue());
            cartItemVO.setTitle(productVO.getTitle());
            cartItemVO.setCoverImg(productVO.getCoverImg());
        }
    }


    /**
     * 获取购物车
     * @return
     */
    private BoundHashOperations<String, Object, Object> getMyCartOps() {
        String cartKey = getCartKey();
        //使用BoundHashOperations操作redis,即使redis中没有对应的购物车类，也可以生成一个可操作对象，不会报错
        //redisTemplate.boundHashOps(cartKey)并不会对redis进行操作，只会返回一个BoundHashOperations对象
        //后续中如果有put等操作，没有购物车对象，会自动生成一个，所以不用另外创建。
        return redisTemplate.boundHashOps(cartKey);
    }
    /**
     * 获取购物车key
     * @return
     */
    private String getCartKey(){
        LoginUser loginUser = LoginInterceptor.threadLocal.get();
        String key = String.format(CacheKey.Cart_KEY, loginUser.getId());
        return key;
    }
}
